const fs = require('fs-extra');
const path = require('path');
const { app } = require('electron');
const { getCaseKnex } = require('../database/knex');

/**
 * PluginManager
 * 负责管理系统中的分析插件 (注册、获取、执行)
 * 支持只需文件 manifest.json 的文件夹结构插件
 * 单例模式
 */
class PluginManager {
    constructor() {
        this.plugins = new Map(); // id -> plugin wrapper
        // 用户插件目录: C:\Users\xxx\AppData\Roaming\sjfx-vue\plugins
        this.userPluginsPath = path.join(app.getPath('userData'), 'plugins');
        this.ensureUserPluginsDir();
    }

    /**
     * 获取单例实例 (保留兼容性)
     */
    static getInstance() {
        if (!PluginManager.instance) {
            PluginManager.instance = new PluginManager();
        }
        return PluginManager.instance;
    }

    ensureUserPluginsDir() {
        if (!fs.existsSync(this.userPluginsPath)) {
            try {
                fs.mkdirSync(this.userPluginsPath, { recursive: true });
            } catch (e) {
                console.error('[PluginManager] Failed to create user plugins dir:', e);
            }
        }
    }

    /**
     * 注册插件对象 (Legacy / Internal)
     * @param {Object} plugin 插件对象
     * @param {string} source 来源 'system' | 'user'
     */
    register(plugin, source = 'system') {
        if (!plugin || !plugin.id) {
            console.error('[PluginManager] Invalid plugin: missing id');
            return false;
        }

        if (this.plugins.has(plugin.id)) {
            console.warn(`[PluginManager] Plugin ${plugin.id} already registered. Overwriting.`);
        }

        // 验证必要的方法
        if (typeof plugin.run !== 'function') {
            console.error(`[PluginManager] Plugin ${plugin.id} missing run() method`);
            return false;
        }

        this.plugins.set(plugin.id, {
            ...plugin,
            _source: source,
            registeredAt: new Date()
        });

        console.log(`[PluginManager] Registered ${source} plugin: ${plugin.name} (${plugin.id})`);
        return true;
    }

    /**
     * 从目录加载单个插件
     * @param {string} dirPath 插件目录路径
     * @param {string} source 来源
     */
    loadFromDirectory(dirPath, source = 'user') {
        try {
            const manifestPath = path.join(dirPath, 'manifest.json');
            if (!fs.existsSync(manifestPath)) {
                // Silect skip if not a plugin dir (or log debug)
                return false;
            }

            const manifestContent = fs.readFileSync(manifestPath, 'utf-8');
            const manifest = JSON.parse(manifestContent);

            // 验证必要字段
            if (!manifest.id || !manifest.name || !manifest.entry) {
                throw new Error('Invalid manifest: missing id, name or entry');
            }

            const entryPath = path.join(dirPath, manifest.entry);
            if (!fs.existsSync(entryPath)) {
                throw new Error(`Entry file not found: ${manifest.entry}`);
            }

            // 加载插件代码
            // 注意：require缓存问题，如果是开发热加载可能需要处理
            // clearCache if needed: delete require.cache[require.resolve(entryPath)];
            const pluginModule = require(entryPath);

            // 合并 manifest 信息和代码逻辑
            // 插件模块可以直接导出对象，或者导出一个类/函数
            // 这里假设导出的是符合标准的 plugin 对象 { run: async fn ... }
            if (!pluginModule.run) {
                throw new Error('Plugin entry module must export an object with run() method');
            }

            const plugin = {
                ...pluginModule, // run and other logic
                // 强制使用 manifest 中的元数据覆盖代码中的（如果冲突）
                id: manifest.id,
                name: manifest.name,
                version: manifest.version,
                description: manifest.description,
                params: manifest.params || [],
                _dir: dirPath
            };

            return this.register(plugin, source);

        } catch (error) {
            console.error(`[PluginManager] Failed to load plugin from ${dirPath}:`, error.message);
            return false;
        }
    }

    /**
     * 加载所有用户插件
     */
    loadUserPlugins() {
        console.log(`[PluginManager] Scanning user plugins from ${this.userPluginsPath}`);
        if (!fs.existsSync(this.userPluginsPath)) return;

        const items = fs.readdirSync(this.userPluginsPath);

        for (const item of items) {
            const itemPath = path.join(this.userPluginsPath, item);
            if (fs.statSync(itemPath).isDirectory()) {
                this.loadFromDirectory(itemPath, 'user');
            }
        }
    }

    /**
     * 导入用户插件
     * @param {string} sourcePath 插件源文件夹路径
     */
    async importPlugin(sourcePath) {
        try {
            // 1. 验证源插件
            const manifestPath = path.join(sourcePath, 'manifest.json');
            if (!fs.existsSync(manifestPath)) {
                throw new Error('导入失败：目录下缺少 manifest.json');
            }
            const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
            if (!manifest.id) throw new Error('manifest.json 缺少 id 字段');

            // 2. 目标路径
            const targetPath = path.join(this.userPluginsPath, manifest.id);

            // 3. 复制文件 (递归)
            this.copyFolderSync(sourcePath, targetPath);

            // 4. 加载
            const success = this.loadFromDirectory(targetPath, 'user');
            if (!success) {
                // 回滚：删除复制的文件
                try {
                    fs.rmdirSync(targetPath, { recursive: true });
                } catch (e) { console.error('Rollback failed', e); }
                throw new Error('插件加载失败，已回滚');
            }

            return { success: true, message: `插件 ${manifest.name} 导入成功` };

        } catch (error) {
            console.error('[PluginManager] Import failed:', error);
            return { success: false, message: error.message };
        }
    }

    copyFolderSync(from, to) {
        if (!fs.existsSync(to)) {
            fs.mkdirSync(to, { recursive: true });
        }

        const files = fs.readdirSync(from);
        for (const file of files) {
            const src = path.join(from, file);
            const dest = path.join(to, file);
            const stat = fs.statSync(src);

            if (stat.isDirectory()) {
                this.copyFolderSync(src, dest);
            } else {
                fs.copyFileSync(src, dest);
            }
        }
    }

    /**
     * 获取所有插件列表
     */
    getAll() {
        return Array.from(this.plugins.values()).map(p => ({
            id: p.id,
            name: p.name,
            version: p.version,
            description: p.description,
            type: p.type,
            source: p._source,
            params: p.params
        }));
    }

    /**
     * 获取指定插件
     * @param {string} id 
     */
    get(id) {
        return this.plugins.get(id);
    }

    /**
     * 执行插件
     * @param {string} pluginId 
     * @param {Object} params 参数
     * @param {Object} context 上下文 (如 db连接, caseId等)
     */
    async execute(pluginId, params, context) {
        const plugin = this.plugins.get(pluginId);
        if (!plugin) {
            throw new Error(`Plugin ${pluginId} not found`);
        }

        try {
            console.log(`[PluginManager] Executing plugin ${pluginId}...`);
            const startTime = Date.now();

            // Inject Helper Function if not present
            const runContext = {
                ...context,
                getKnex: getCaseKnex
            };

            const result = await plugin.run(runContext, params);

            const duration = Date.now() - startTime;
            console.log(`[PluginManager] Plugin ${pluginId} finished in ${duration}ms`);

            return {
                success: true,
                data: result,
                meta: {
                    pluginId,
                    pluginName: plugin.name,
                    duration,
                    timestamp: new Date()
                }
            };
        } catch (error) {
            console.error(`[PluginManager] Plugin ${pluginId} execution failed:`, error);
            throw error; // Let caller handle or wrap
        }
    }
}

module.exports = PluginManager.getInstance();
